#include "luat_network_adapter.h"
#include "common_api.h"
#include "luat_debug.h"
#include "luat_mem.h"
#include "luat_rtos.h"
#include "luat_mobile.h"

#include "libemqtt.h"
#include "luat_mqtt.h"
#include "luat_mcu.h"
#include "main.h"

// 是否自动重连
#define MQTT_DEMO_AUTOCON 		1
// 上行时的QOS值
#define MQTT_DEMO_PUB_QOS 		1
#define MAX_MQTT_TRY_CONNECT_TIMES (25)
// MQTT服务器信息, 仅支持MQTT3.1.1协议, 不支持 3.1和5.0协议, 不支持 mqtt over websocket
// #if (MQTT_DEMO_SSL == 1)
// #define MQTT_HOST    	"122.51.98.166"   				// MQTTS服务器的地址和端口号
// #define MQTT_PORT		1883      
// #define USERNAME    	"112233"                 
// #define PASSWORD    	"112233"   
// #define MQTT_HOST    	"gps-lot-258272.hainabaichuang.cn"   				// MQTTS服务器的地址和端口号
// #define MQTT_PORT		1883      
// #define USERNAME    	"gps_car"                 
// #define PASSWORD    	"xifh9j24reg@X3nmO"   
// #define MQTT_HOST    	"airtest.openluat.com"   				// MQTTS服务器的地址和端口号
// #define MQTT_PORT		8883      
// #define USERNAME    	"user"                 
// #define PASSWORD    	"password"   
// #else
// #define MQTT_HOST    	"lbsmqtt.airm2m.com"   				// MQTT服务器的地址和端口号
// #define MQTT_PORT		1884
// #define USERNAME    	"username"                 
// #define PASSWORD    	"password"   
// #endif 

#define CLIENT_ID    	"123456789"         // 缺省ClientId, 本demo会用IMEI号填充


/**
 * 订阅topic
 */
char sub_topic_control[MAX_TOPIC_LEN];
char sub_topic_config[MAX_TOPIC_LEN];
/**
 * 发布topic
 */
char pub_topic_online[MAX_TOPIC_LEN];
char pub_topic_offline[MAX_TOPIC_LEN];
char pub_topic_onreport[MAX_TOPIC_LEN];
char pub_topic_onchange[MAX_TOPIC_LEN];
char pub_topic_onalarm[MAX_TOPIC_LEN];
char pub_topic_ping[MAX_TOPIC_LEN];
char pub_topic_oncontrol[MAX_TOPIC_LEN];


static char mqtt_client_id[32] = {0};
static luat_rtos_task_handle mqtt_task_handle;
static luat_rtos_task_handle mqtt_pub_task_handle;
static luat_rtos_queue_t mqtt_queue_handle;
static luat_rtos_queue_t mqtt_pub_queue_handle;

typedef struct{
	luat_mqtt_ctrl_t *luat_mqtt_ctrl;
	uint8_t *buff;
	uint16_t event;
} mqttQueueData;

typedef struct{
	char *topic;
	char *msg;
} mqttQueuePubData;

#define MQTT_DEMO_UART_ID 		1
#define MQTT_DEMO_UART_BAUD 	115200

// MQTT控制器句柄
static luat_mqtt_ctrl_t *g_luat_mqtt_ctrl;
static luat_rtos_task_handle mqtt_task_handle;


void luat_mqtt_cb(luat_mqtt_ctrl_t *luat_mqtt_ctrl, uint16_t event)
{
	mqttQueueData mqtt_cb_event = {.luat_mqtt_ctrl = luat_mqtt_ctrl,.event = event};
	luat_rtos_queue_send(mqtt_queue_handle, &mqtt_cb_event, NULL, 0);
	return;
}
LUAT_MQTT_STATE_E get_mqtt_status(DEV_LTE_T *lte)
{
	luat_rtos_mutex_lock(lte->mutex, LUAT_WAIT_FOREVER);
	LUAT_MQTT_STATE_E state = lte->mqtt_status;
	luat_rtos_mutex_unlock(lte->mutex);
	return state;
}
void mqtt_pub_task(void *param)
{
	mqttQueuePubData mqttQueueSend = {0};
	luat_rtos_queue_create(&mqtt_pub_queue_handle, MQTT_QUEUE_SIZE, sizeof(mqttQueuePubData));
	while(1)
	{
		if (luat_rtos_queue_recv(mqtt_pub_queue_handle, &mqttQueueSend, NULL, 5000) == 0){
			//  usr_log("topic = %s",mqttQueueSend.topic);
			//  usr_log("msg = %s",mqttQueueSend.msg);
			if(get_mqtt_status(&g_dev_lte) == MQTT_STATE_READY)
			{
				mqtt_publish_with_qos(&(g_luat_mqtt_ctrl->broker), mqttQueueSend.topic, mqttQueueSend.msg, strlen(mqttQueueSend.msg), 0, 0, NULL);
			}
			free(mqttQueueSend.msg);
		}
	}
}

void set_mqtt_status(DEV_LTE_T *lte, LUAT_MQTT_STATE_E state)
{
	luat_rtos_mutex_lock(lte->mutex, LUAT_WAIT_FOREVER);
	lte->mqtt_status = state;
	luat_rtos_mutex_unlock(lte->mutex);
}
// MQTT主任务
static void mqtt_task(void *param)
{
	int ret = -1;
	char mqtt_send_payload[80] = {0};
	// while (get_4g_net_status(&g_dev_lte) == NET_UNCONNECT || get_4g_sim_status(&g_dev_lte) != SIM_READY)
	// {
	// 	usr_delay_s(1);
	// }
	// 对mqtt的信息进行初始化
	//usr_log("1. create task queue");
	mqttQueueData mqttQueueRecv = {0};
	luat_rtos_queue_create(&mqtt_queue_handle, MQTT_QUEUE_SIZE, sizeof(mqttQueueData));
	luat_rtos_task_create(&mqtt_pub_task_handle, 2 * 1024, 10, "mqtt_pub_task", mqtt_pub_task, NULL, 16);

	// 创建网络适配器承载
	//usr_log("2. create network ctrl");
	set_mqtt_status(&g_dev_lte, MQTT_STATE_SCONNECT);

	// 首先是client id
	if (mqtt_client_id[0] == 0) {
		ret = luat_mobile_get_imei(0, mqtt_client_id, sizeof(mqtt_client_id)-1);
		if(ret <= 0){
			//LUAT_DEBUG_PRINT("imei get fail!!!!!");
			memcpy(mqtt_client_id, CLIENT_ID, strlen(CLIENT_ID));
		}
	}

	// 然后是topic
	config_mqtt_topic(mqtt_client_id);
	g_luat_mqtt_ctrl = (luat_mqtt_ctrl_t *)luat_heap_malloc(sizeof(luat_mqtt_ctrl_t));
	ret = luat_mqtt_init(g_luat_mqtt_ctrl, NW_ADAPTER_INDEX_LWIP_GPRS);
	if (ret) {
		//LUAT_DEBUG_PRINT("mqtt init FAID ret %d", ret);
		return;
	}
	g_luat_mqtt_ctrl->ip_addr.type = 0xff;
	luat_mqtt_connopts_t opts = {0};
	opts.is_tls = 0;
	opts.host = g_dev_info->info.addr;//MQTT_HOST;//get_mqtt_addr(&g_dev_info);
	opts.port = g_dev_info->info.port;//MQTT_PORT;//get_mqtt_port(&g_dev_info);
	ret = luat_mqtt_set_connopts(g_luat_mqtt_ctrl, &opts);

	mqtt_init(&(g_luat_mqtt_ctrl->broker), mqtt_client_id);
	mqtt_init_auth(&(g_luat_mqtt_ctrl->broker), USERNAME, PASSWORD);

	// luat_mqtt_ctrl->netc->is_debug = 1;   // 开启底层debug信息
	g_luat_mqtt_ctrl->keepalive = 240;         // MQTT PING 间隔
	g_luat_mqtt_ctrl->broker.clean_session = 1;

	if (MQTT_DEMO_AUTOCON == 1) // 自动重连
	{
		g_luat_mqtt_ctrl->reconnect = 1;
		g_luat_mqtt_ctrl->reconnect_time = 3000; // 延迟3秒重连
	}

	// 测试遗嘱
	 sprintf(mqtt_send_payload, "{\"uid\":\"%s\"}",mqtt_client_id);//离线消息	
	 luat_mqtt_set_will(g_luat_mqtt_ctrl, pub_topic_offline, mqtt_send_payload, strlen(mqtt_send_payload), 0, 0); 
	
	luat_mqtt_set_cb(g_luat_mqtt_ctrl,luat_mqtt_cb);
	//LUAT_DEBUG_PRINT("mqtt_connect");
	ret = luat_mqtt_connect(g_luat_mqtt_ctrl);
	if (ret) {
		// 发起连接, 非阻塞的
	//	LUAT_DEBUG_PRINT("mqtt connect ret=%d\n", ret);
		luat_mqtt_close_socket(g_luat_mqtt_ctrl);
		return;
	}
	//LUAT_DEBUG_PRINT("wait mqtt_state ...");
	uint8_t wait_times = MAX_MQTT_TRY_CONNECT_TIMES;
	do
	{
		// usr_log("wait_times = %d", wait_times);
		// usr_log("g_luat_mqtt_ctrl->mqtt_state = %d", g_luat_mqtt_ctrl->mqtt_state);
		// usr_log("mqtt_state = %d", luat_mqtt_state_get(g_luat_mqtt_ctrl));
		set_mqtt_status(&g_dev_lte, g_luat_mqtt_ctrl->mqtt_state);
		luat_rtos_task_sleep(5000);
	} while (wait_times-- && get_mqtt_status(&g_dev_lte) != MQTT_STATE_READY);

	//usr_log("mqtt_state = %d", g_luat_mqtt_ctrl->mqtt_state);

	/*mqtt连接失败*/
	if (get_mqtt_status(&g_dev_lte) != MQTT_STATE_READY)
	{
		//usr_log("mqtt connect failed");
		luat_os_reboot(0);
	}
	//usr_log("mqtt connect success");
	uint16_t message_id = 0;
		
	// uint32_t all,now_used_block,max_used_block;
	work_led_mode_switch(&gsm_work_led, MODE_DATA);
	data_mode_count_add(&gsm_work_led);
	while(1){
		if (luat_rtos_queue_recv(mqtt_queue_handle, &mqttQueueRecv, NULL, 5000) == 0){
			switch (mqttQueueRecv.event)
			{
			case MQTT_MSG_CONNACK:
				ret = mqtt_subscribe(&(g_luat_mqtt_ctrl->broker), sub_topic_control, &message_id, 1);
				ret = mqtt_subscribe(&(g_luat_mqtt_ctrl->broker), sub_topic_config, &message_id, 1);
				luat_rtos_message_send(message_event_deal_task_handle, CASE_TASK_ON_REPORT, (void *)NULL);
				/*开机声音*/
				//beep_player.play_num=1;
				break;
			case MQTT_MSG_PUBLISH:
			{
				const uint8_t *topic, *payload;
				uint16_t topic_len = mqtt_parse_pub_topic_ptr(mqttQueueRecv.luat_mqtt_ctrl->mqtt_packet_buffer, &topic);
				uint16_t payload_len = mqtt_parse_pub_msg_ptr(mqttQueueRecv.luat_mqtt_ctrl->mqtt_packet_buffer, &payload);
				mqtt_msg_handler(topic, topic_len, payload);
				break;
			}
			case MQTT_MSG_PUBACK:
			case MQTT_MSG_PUBCOMP:
			{
				//LUAT_DEBUG_PRINT("msg_id: %d", mqtt_parse_msg_id(mqttQueueRecv.luat_mqtt_ctrl->mqtt_packet_buffer));
				break;
			}
			case MQTT_MSG_RECONNECT:
			{
				//usr_log("->>>>mqtt reconnect");
				break;
			}
			case MQTT_MSG_RELEASE:
			{
				//LUAT_DEBUG_PRINT("luat_mqtt_cb mqtt release");
				break;
			}
			case MQTT_MSG_CLOSE : { // mqtt 关闭(不会再重连)  注意：一定注意和MQTT_MSG_DISCONNECT区别，如果要做手动重连处理推荐在这里 */
				if (MQTT_DEMO_AUTOCON == 0)
				{
					work_led_mode_switch(&gsm_work_led, MODE_INIT);
					while (1) 
					{
						luat_rtos_task_sleep(3000);
						ret = luat_mqtt_connect(mqttQueueRecv.luat_mqtt_ctrl);
						if (ret) {
							luat_mqtt_close_socket(mqttQueueRecv.luat_mqtt_ctrl);							
							luat_rtos_task_sleep(1000);
							luat_os_reboot(0);
						}
						uint8_t wait_times = MAX_MQTT_TRY_CONNECT_TIMES;
						do
						{
							set_mqtt_status(&g_dev_lte, mqttQueueRecv.luat_mqtt_ctrl->mqtt_state);
							luat_rtos_task_sleep(5000);
						} while (wait_times-- && !(get_mqtt_status(&g_dev_lte) == MQTT_STATE_READY));
						/*mqtt连接失败*/
						if (get_mqtt_status(&g_dev_lte) != MQTT_STATE_READY)
						{							
							luat_rtos_task_sleep(1000);
							luat_os_reboot(0);
						}
						work_led_mode_switch(&gsm_work_led, MODE_DATA);
						break;
					}
				}
				break;
			}
			default:
				break;

			}
		}
	}

	// task结束, 删除自身
	luat_rtos_task_delete(mqtt_task_handle);
}

void config_mqtt_topic(char *imei)
{
	sprintf(sub_topic_control, "Gps/%s/control", imei);
	sprintf(sub_topic_config, "Gps/%s/config", imei);
	sprintf(pub_topic_online, "Gps/%s/onLine", imei);
	sprintf(pub_topic_offline, "Gps/%s/offline", imei);
	sprintf(pub_topic_onreport, "Gps/%s/onreport", imei);
	sprintf(pub_topic_onchange, "Gps/%s/onchange", imei);
	sprintf(pub_topic_onalarm, "Gps/%s/onalarm", imei);
	sprintf(pub_topic_ping, "Gps/%s/ping", imei);
	sprintf(pub_topic_oncontrol, "Gps/%s/oncontrol", imei);
}
void luatos_mobile_event_callback(LUAT_MOBILE_EVENT_E event, uint8_t index, uint8_t status)
{
	char apn[32] = {0};
	ip_addr_t ipv4;
	ip_addr_t ipv6;
	struct tm tblock = {0};
	switch (event)
	{
	case LUAT_MOBILE_EVENT_SIM:
		if (status != LUAT_MOBILE_SIM_NUMBER)
		{
			//LUAT_DEBUG_PRINT("SIM卡消息,卡槽%d", index);
		}
		switch (status)
		{
		case LUAT_MOBILE_SIM_READY:
			LUAT_DEBUG_PRINT("SIM卡正常工作");
			/*1.record ccid*/
			set_4g_ccid(&g_dev_lte, index);
			/*2.record imsi*/
			set_4g_imsi(&g_dev_lte, index);
			/*3.record imei*/
			set_4g_imei(&g_dev_lte, index);
			/*4.record sim status is SIM_READY*/
			set_4g_sim_status(&g_dev_lte, SIM_READY);
			break;
		case LUAT_MOBILE_NO_SIM:
			LUAT_DEBUG_PRINT("SIM卡不存在");
			/* 1.record sim status is NO_SIM */
			set_4g_sim_status(&g_dev_lte, NO_SIM);
			/* 2.dev reboot */
			luat_os_reboot(0);
			break;
		// case LUAT_MOBILE_SIM_NEED_PIN:
		// 	LUAT_DEBUG_PRINT("SIM卡需要输入PIN码");
		// 	break;
		}
		break;
	case LUAT_MOBILE_EVENT_CELL_INFO:
		switch (status)
		{
		case LUAT_MOBILE_SIGNAL_UPDATE:
			LUAT_DEBUG_PRINT("服务小区信号状态变更");
			luat_mobile_get_last_notify_signal_strength(&g_dev_lte.csq);
			break;
		}
		break;
	case LUAT_MOBILE_EVENT_NETIF:
		LUAT_DEBUG_PRINT("internet工作状态变更为 %d,cause %d", status, index);
		switch (status)
		{
		case LUAT_MOBILE_NETIF_LINK_ON:
			//usr_log("net connect success");
			/*1.record net status*/
			set_4g_net_status(&g_dev_lte, NET_CONNECTED);

			//luat_socket_check_ready(index, NULL);
			if (luat_mobile_get_apn(0, 0, apn, sizeof(apn)))
			{
				LUAT_DEBUG_PRINT("默认apn %s", apn);
			}
			luat_mobile_get_local_ip(0, 1, &ipv4, &ipv6);
			if (ipv4.type != 0xff)
			{
				usr_log("IPV4 %s", ip4addr_ntoa(&ipv4.u_addr.ip4));
			}
			if (ipv6.type != 0xff)
			{
				usr_log("IPV6 %s", ip6addr_ntoa(&ipv4.u_addr.ip6));
			}
			break;
		default:
			usr_log("不能上网");
			break;
		}
		break;
	case LUAT_MOBILE_EVENT_TIME_SYNC:
		LUAT_DEBUG_PRINT("通过移动网络同步了UTC时间");		
		luat_rtc_get(&tblock);
		LUAT_DEBUG_PRINT("%04d/%02d/%02d/ %02d:%02d:%02d %02d", tblock.tm_year+1900, tblock.tm_mon+1, tblock.tm_mday, tblock.tm_hour, tblock.tm_min,tblock.tm_sec,tblock.tm_wday);
		break;
	case LUAT_MOBILE_EVENT_FATAL_ERROR:
		LUAT_DEBUG_PRINT("网络严重故障，建议重启协议栈");
		luat_mobile_reset_stack();
		break;
	default:
		break;
	}
	
}



void my_mqtt_init(void)
{
	luat_mobile_set_sim_detect_sim0_first();
	luat_mobile_event_register_handler(luatos_mobile_event_callback);
	luat_rtos_task_create(&mqtt_task_handle, 8 * 1024, 10, "mqtt_task", mqtt_task, NULL, 16);
}






/**
 * mqtt发送函数
 */
void usr_mqtt_pub_msg(char *msg, char *topic)
{
	mqttQueuePubData pubData = {.msg = msg, .topic = topic};
	luat_rtos_queue_send(mqtt_pub_queue_handle, &pubData, NULL, 0);
}

